package xyz.scootaloo.kami.server.service

import io.vertx.core.Future
import io.vertx.core.Promise
import xyz.scootaloo.kami.server.verticle.vertx

/**
 * @author flutterdash@qq.com
 * @since 2022/1/11 0:44
 */

typealias CodeBlock<T> = () -> T
typealias CommandBlock = CodeBlock<Unit>
typealias PromiseCodeBlock<T> = (Promise<T>) -> Unit

object Sync {
    fun run(block: CommandBlock): Future<Unit> = safeExecuteBlocking(true, block)
    operator fun <T> invoke(block: PromiseCodeBlock<T>): Future<T> = executeBlockingWithPromise(true, block)
}

object Async {
    fun run(block: CommandBlock): Future<Unit> = safeExecuteBlocking(false, block)
    operator fun <T> invoke(block: PromiseCodeBlock<T>): Future<T> = executeBlockingWithPromise(false, block)
}

private fun <T> safeExecuteBlocking(sync: Boolean, block: CodeBlock<T>): Future<T> {
    return vertx.executeBlocking({ promise ->
        try {
            val rtn = block()
            promise.complete(rtn)
        } catch (error: Throwable) {
            promise.fail(error)
        }
    }, sync)
}

private fun <T> executeBlockingWithPromise(sync: Boolean, block: PromiseCodeBlock<T>): Future<T> {
    return vertx.executeBlocking(block, sync)
}